﻿#include <vtkSmartPointer.h>
#include <vtkImageViewer2.h>
#include <vtkDICOMImageReader.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkImageData.h>
#include <vtkInformation.h>

#include <opencv2/core.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include "vtkAutoInit.h"
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);

// 读取一个dicom文件
int main(int argc, char* argv[])
{
    // Verify input arguments
    if ( argc != 2 )
    {
        std::cout << "Usage: " << argv[0]
                  << " Filename(.img) e.g. prostate.img" << std::endl;
        return EXIT_FAILURE;
    }
    
    std::string inputFilename = argv[1];
    
    // Read all the DICOM files in the specified directory.
    vtkSmartPointer<vtkDICOMImageReader> reader =
            vtkSmartPointer<vtkDICOMImageReader>::New();
    reader->SetFileName(inputFilename.c_str());
    reader->Update();
    //reader->Print(cout);
    //reader->GetInformation()->Print(cout);
    
    vtkImageData* imageData = reader->GetOutput();
    // imageData->Print(cout);

    // 获取原图像数据的灰度值范围
    // 如：CT值的单位是Hounsfield，简称为Hu，范围是-1024-3071。用于衡量人体组织对X射线的吸收率，设定水的吸收率为0Hu。
    double range[2];
    imageData->GetScalarRange(range);
    cout << "range: " << range[0] << ", " << range[1] << endl;
    cout << "GetScalarTypeAsString (): " << imageData->GetScalarTypeAsString () << endl;

    // Visualize
    vtkSmartPointer<vtkImageViewer2> imageViewer =
            vtkSmartPointer<vtkImageViewer2>::New();
    imageViewer->SetInputConnection(reader->GetOutputPort());
    imageViewer->SetColorLevel((range[1]+range[0])/2);
    imageViewer->SetColorWindow(range[1]-range[0]);
    
    //imageViewer->Print(cout);
    vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
            vtkSmartPointer<vtkRenderWindowInteractor>::New();
    imageViewer->SetupInteractor(renderWindowInteractor);
    imageViewer->Render();
    imageViewer->GetRenderer()->ResetCamera();
    imageViewer->Render();
    


    cout << "DICOM inforamtion:" << endl;
    cout << "reader[w, h]: " << reader->GetWidth() << ", " << reader->GetHeight() << endl;
    float rescaleSlope = reader->GetRescaleSlope();
    cout << "rescaleSlope: " << rescaleSlope << endl;
    float rescaleOffset = reader->GetRescaleOffset();
    cout << "rescaleOffset: " << rescaleOffset << endl;

    // 处理数据并生成图像
    {
        int type = imageData->GetScalarType();
        if (type == VTK_UNSIGNED_SHORT) {
            int dims[3];
            imageData->GetDimensions(dims);
            int rows = dims[1];
            int cols = dims[0];
            cv::Mat img1 = cv::Mat(rows, cols, CV_8U);
            ushort *pdata = static_cast<ushort*>(imageData->GetScalarPointer());
            double thresholdV1 = (range[0] + range[1]) / 2.0;
            double factor = 255.0/thresholdV1;
            for(int y= 0; y< rows; y++) {
                uchar *ptr = img1.ptr<uchar>(y);
                for (int x=0; x< cols; x++) {
                    short vPixel =  thresholdV1 - pdata[rows *y +x];
                    ptr[x] = vPixel > 0 ? vPixel * factor : 255;
                }
            }
            cv::imwrite("/home/grind/test.png", img1);
        }
    }
    renderWindowInteractor->Start();
    
    return EXIT_SUCCESS;
}
